iT邦幫忙

2023 iThome 鐵人賽

DAY 7
0
AI & Data

AI白話文運動系列之「A!給我那張Image!」系列 第 7

Pytorch實戰(一)--準備資料集(Dataset, DataLoader, transforms...)

  • 分享至 

  • xImage
  •  

前言

在前幾天的內容中,我們談到了AI模型的運作與更新方式,也介紹了Pytorch這項好用的工具。在昨天更是看到了AI形模型是如何模擬人腦的運作。今明兩天,我們將利用pytorch展示如何從頭開始建立自己的AI模型。

先備知識

  1. Python(至少對Python語法不陌生)
  2. 物件導向(至少需要知道class, function等概念)

看完今天的內容你可能會知道......

  1. AI模型訓練的流程
  2. 如何準備AI模型所需的訓練資料
  3. 資料前處理(Data preprocessing)與資料擴充(Data augmentation)是甚麼

一、AI模型訓練流程

  • 要從頭開始建立、訓練一個AI模型主要有以下幾個步驟:準備資料集(dataset)、建立模型架構、訓練模型、測試模型表現,今天我們將從最前面的步驟開始談起。

二、AI模型的資料準備

  • 在Pytorch中有三種常見的方式可以獲取我們所需要的資料集,下面會根據使用難度,由易到難依序展開介紹:

    1. torchvision.datasets

    • 參考資料:https://pytorch.org/vision/stable/datasets.html
    • Pytorch中有提供許多內建的資料集,這些資料集已經被固定的格式包裝好,可以直接呼叫出來使用,在上述網站中也依照不同的任務類型,將不同的資料集分類列出,使用的時候可以根據所需要的任務找到適合的資料集。
    • 接下來,我們來看看要怎麼使用這樣的工具,以最常見的分類任務資料集MNIST為例,我們可以從上述網站中找到這個資料集,然後進一步點開看該資料集的頁面:https://pytorch.org/vision/stable/generated/torchvision.datasets.MNIST.html#torchvision.datasets.MNIST ,裡面詳細的靠訴我們這個資料集的格式與使用方式,每一項參數所代表的意義也都有詳細的說明,所以我們可以跟著這樣的說明走:
    import torch
    import torchvision
    import torchvision.transforms as transforms
    
    transform = transforms.Compose([transforms.ToTensor(), transforms.Normalize((0.5,), (0.5,))])
    
    train_dataset = torchvision.datasets.MNIST(root='./data', train=True, transform=transform, download=True)
    print(train_dataset.__getitem__(10))
    print(train_dataset.__len__)
    
    • 在上面的程式碼中,我們定義了一個轉換transform,這個動作的目的在於對所有資料集中的資料「統一進行某種操作」,操作可以是型態轉換(tensor跟numpy資料型態互換)、基礎影像處理(crop, normalize等操作)或是自定義的其餘操作等等,簡單來說就是一個可以快速調整資料的方式,這個部分更多的內容會在下面的補充章節中討論。
    • 每個torchvision中提供的dataset都有兩個固定的函式,一個是.__lne__(),一個是.__getitem__(index),前者可以告訴我們這個資料集的大小,後者則是在給定特定index的情況下,告訴你這筆資料裡面包含了甚麼,通常是(影像,標籤)這樣的格式。
    • 更多的操作方式可以參考:https://pytorch.org/tutorials/beginner/basics/data_tutorial.html
  • 除了直接使用Pytorch中提供的影像資料以外,有時候,我們想要在自己的影像資料上訓練自己的模型,這個時候我們可以下面兩種方式:

    2. torchvision.datasets.ImageFolder

    3. 客製化dataset

    import os
    import pandas as pd
    from torchvision.io import read_image
    
    class CustomImageDataset(Dataset):
        def __init__(self, annotations_file, img_dir, transform=None, target_transform=None):
            self.img_labels = pd.read_csv(annotations_file)
            self.img_dir = img_dir
            self.transform = transform
            self.target_transform = target_transform
    
        def __len__(self):
            return len(self.img_labels)
    
        def __getitem__(self, idx):
            img_path = os.path.join(self.img_dir, self.img_labels.iloc[idx, 0])
            image = read_image(img_path)
            label = self.img_labels.iloc[idx, 1]
            if self.transform:
                image = self.transform(image)
            if self.target_transform:
                label = self.target_transform(label)
            return image, label
    
    • 建立自己的資料集的關鍵是__len__()__getitem__()這兩個函式,最上面的__init__函式是輔助作用,在我們將一個這樣的資料集實例化之後,第一個會執行的函式,所以可以在這邊定義一些後續會需要用到的東西。
    • 正如前面所介紹到的,.__lne__().__getitem__(index)這兩個函式,必須要回傳資料集的大小以及特定index的那筆資料所包含的東西。以上面的程式碼為例,我們將所有影像的資訊透過csv檔讀進來,並且保存在self.img_labels中,接著在def __getitem__(self, idx)裡面,我們剛剛存下來的影像資訊,把每張影像的「路徑」與「標註(Label)」都取出來,分別用image, label表示。

    4. 批次包裝--DataLoader

    • 之前有介紹過,我們通常在訓練一個AI模型的時候,不會是一筆資料一筆資料的送入模型裡面訓練,一來是因為這樣太慢了,二來是,如果今天某一筆資料是離群值/極端值(可以想成是跟其他資料長的超級布一樣的資料),這時候我們的模型就會因為這筆資料產生非常大的變動,使模型從一大堆正常的結果中往少數極端的結果靠近,這是我們不希望看到的,所以我們在訓練AI模型的時候,會一批一批資料的送進去訓練,每一批資料有多少可以看我們的需求而定。
    • 實際上,我們可以使用torch.utils.data中的DataLoader來幫助我們將已經建立好的dataset包裝成一批一批的資料,就像Pytorch中提供的範例:
    from torch.utils.data import DataLoader
    
    train_dataloader = DataLoader(training_data, batch_size=64, shuffle=True)
    test_dataloader = DataLoader(test_data, batch_size=64, shuffle=True)
    
    • 這邊就可以看出來Dataset與DataLoader最大的區別了,前者是一筆一筆的資料(記得,我們利用.__getitem__(index)函式來回傳資料),後者則是一批一批的資料。

三、補充--transforms

  • 前面有大致介紹到transforms被我們用來對整個資料集中的每一筆資料統一進行某種操作,這樣的操作主要可以分兩類:資料前處理(Data preprocessing)與資料擴充(Data augmentation)。
  • 資料前處理是指將資料送入模型之前,對資料進行清洗、整合、格式轉換等操作,目的在於讓模型不要受到離群值/極端值的影響,詳細的內容可以參考:https://ithelp.ithome.com.tw/articles/10186204
  • 資料擴充就像字面上看到的,我們要將資料變多變廣,這是因為我們的模型好壞,除了受到模型架構的影響以外,很大程度會受到訓練資料的影響,如果這些資料的數量不夠,多樣性不夠,那麼我們的模型很容易學到偏差的結果,讓模型只認得某些固定的特徵或樣式。舉例來說的話,如果今天要做貓狗分類的任務,可是狗的圖片只有赤色的柴犬,那麼訓練好的模型,如果遇到其他顏色的柴犬或是其他種類的狗的話,就會判斷失誤。所以在資料擴充時,我們會針對顏色、影像幾何變化等方式調整輸入的圖片,讓訓練資料變得更多,也變得更多元。
  • Pytorch的網站(https://pytorch.org/vision/0.15/transforms.html)中有將不同類型的操作列出來,如果有感興趣的話,可以將不同的transforms加入我們最一開始討論的程式碼中,看看會有什麼樣的效果。

四、總結

  • 在今天的內容中,我們主要討論了兩個面向,一個是如何準備AI模型所需要的訓練資料,然後進一步包裝成批次資料,以利模型訓練,另一個是資料前處理與資料擴充技術,這些技術可以幫助提升我們模型的表現,讓我們的模型有更好的適應性,不會遇到沒看過的資料就判斷失敗。

上一篇
番外篇—AI怎麼學?梯度下降法與反向傳播
下一篇
Pytorch實戰(二)--建立與訓練模型--以MLP為例
系列文
AI白話文運動系列之「A!給我那張Image!」30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言